
// peterson lock
// who = 0 for cpu
// who = 1 for devctl
#define plk_init(plk) {bzero (&plk,sizeof(plk));}
#define plk_lock(plk, who) { \
    plk.flag[who] = 1; \
    plk.victim = who; \
    while (plk.flag[(who+1)%2]==1 && plk.victim==who); \
}

#define plk_unlock(plk, who) { \
    plk.flag[who] = 0; \
}

#define mlk_init(lk) (pthread_mutex_init(&lk,NULL))
#define mlk_lock(lk) if(pthread_mutex_lock (&lk)){fprintf(stderr,"!!MUTEX ERROR(LOCK)");exit(EXIT_FAILURE);}
#define mlk_unlock(lk) if(pthread_mutex_unlock (&lk)){fprintf(stderr,"!!MUTEX ERROR(UNLOCK)");exit(EXIT_FAILURE);}

#define PLK_CPU 0
#define PLK_DEVCTL 1

#define DBG_LOG(domain,fmt,arg...) {if(PARAM_DEBUG){printf("DEBUG:%s: ", #domain);printf(fmt,##arg);printf("\n");fflush(stdout);}}
#define MAGIC_OK(obj) (obj->magic==BISCUIT_MAGIC)

#define MEM_BARRIER {__asm__ __volatile__("": ::"memory");}
//void panic (const char * msg);

status cpu_init (struct rv32cpu* cpu, struct environ* env); 
status cpu_ctrl (struct rv32cpu * cpu, enum cpu_ctl_arg arg);
status cpu_raise_excep_sync (struct rv32cpu * cpu, word cause);
status cpu_raise_excep_async (struct rv32cpu * cpu, word cause);
status cpu_add_module (struct rv32cpu * cpu, struct module * mod);
status cpu_remove_module(struct rv32cpu * cpu, modid_t modid);

status env_init (struct environ * env, uint32 memsz);
status env_ctrl (struct environ * env, enum env_ctl_arg arg);
status env_add_module (struct environ * env, struct module * mod);
status env_remove_module (struct environ * env, modid_t modid);
status env_mod_ctrl (struct environ * env, modid_t modid, enum mod_ctl_arg arg, uint64 exarg);
status env_csrrw_sync (struct environ * env, csraddr_t addr, word send, word * recv, enum rwmod rw);
status env_csrrw_async (struct environ* env, csraddr_t addr, word send, word * recv, enum rwmod rw, struct req_stat * async_stat);

status mem_init (struct memory * mem, uint32 size, struct environ * env);
status mem_add_module (struct memory * mem, struct module * mod);
status mem_remove_module (struct memory * mem, modid_t modid);
status mem_rw_virt (struct environ* env, memaddr_t addr, word send, word * recv, enum rwmod rw);
status mem_rw_phy (struct environ* env, memaddr_t addr, word send, word * recv, enum rwmod rw);

status devctl_init (struct devctl * dctl, struct environ * env);
status devctl_raise_excep_async (struct devctl * dctl, word cause);
status devctl_csrrw_sync (struct devctl* dctl, csraddr_t addr, word send, word * recv, enum rwmod rw);
status devctl_add_module (struct devctl * dctl, struct module * mod);
status devctl_remove_module(struct devctl * dctl, modid_t modid);
status devctl_ctrl(struct devctl * dctl, enum dev_ctl_arg arg);

status modlist_add (struct modlist * list, struct module * mod);
status modlist_init (struct modlist * list);
status modlist_install_all (struct environ * env,struct modlist * list);

status kl_load_kernel (const char* kernel_path, int8* mem, uint32 max_mem);